﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using XSystem.Security.Cryptography;
using ICryptoTransform = System.Security.Cryptography.ICryptoTransform;
using MD5CryptoServiceProvider = XSystem.Security.Cryptography.MD5CryptoServiceProvider;

namespace SimpleORM.Infrastructure.GetToken
{
    public class TokenManagement
    {
        /// <summary>
        /// 生成token
        /// </summary>
        /// <returns></returns>
        public string GenerationToken(string Str1)
        {

            try
            {
                string tokenStr = "";

                string Key = "YisufeiEvaluationSystem@SYSTEM"; //添加关键字

                //获取随机数
                tokenStr = GetRandomNumbers(10);
                tokenStr = tokenStr + Key;
                string SrcContent = string.Join(",", tokenStr);//加入，隔开

                SrcContent = HmacSHA256(SrcContent, "");

                //88afdbb471ed9fbd274596a3b4778230
                //编码一下
                SrcContent = HttpUtility.UrlEncode(SrcContent);

                string sign = GetMD5(SrcContent, "utf-8").ToUpper();//utf8编码格式以及转换为小写


                //返回签名结果
                return sign + CommonAESEncrypt(Str1);
            }
            catch (Exception ex)
            {
                throw new ArgumentException("获取Token失败");
            }

        }
        /// <summary>
        /// 生成加密token
        /// </summary>
        /// <param name="Str1">用户名</param>
        /// <param name="Str2">密码</param>
        /// <returns>加密的token</returns>
        public string GenerationToken(string Str1, string Str2)
        {

            try
            {
                string UtokenStr = "";
                string PtokenStr = "";

                string Key = "YisufeiEvaluationSystem@SYSTEM"; //添加关键字
                #region 加密用户名
                //获取随机数
                UtokenStr = GetRandomNumbers(10);
                UtokenStr = UtokenStr + Key;
                string USrcContent = string.Join(",", UtokenStr);//加入，隔开

                USrcContent = HmacSHA256(USrcContent, "");

                //88afdbb471ed9fbd274596a3b4778230
                //编码一下
                USrcContent = HttpUtility.UrlEncode(USrcContent);

                string Usign = GetMD5(USrcContent, "utf-8").ToUpper();//utf8编码格式以及转换为大写

                //返回签名结果
                Usign += CommonAESEncrypt(Str1);
                #endregion

                #region 加密密码
                //获取随机数
                PtokenStr = GetRandomNumbers(10);
                PtokenStr = PtokenStr + Key;
                string PSrcContent = string.Join(",", PtokenStr);//加入，隔开

                PSrcContent = HmacSHA256(PSrcContent, "");

                //编码一下
                PSrcContent = HttpUtility.UrlEncode(PSrcContent);

                string Psign = GetMD5(PSrcContent, "utf-8").ToUpper();//utf8编码格式以及转换为大写

                //返回签名结果
                Psign += CommonAESEncrypt(Str2);
                return Usign + Psign;
                #endregion
            }
            catch (Exception ex)
            {

                throw new ArgumentException("获取Token失败");
            }

        }
        /// <summary>
        /// 获取随机数
        /// </summary>
        /// <param name="CodeCount">随机数的位数</param>
        /// <returns>返回随机数</returns>
        public string GetRandomNumbers(int CodeCount)
        {
            string allChar = "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,i,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z";
            string[] allCharArray = allChar.Split(',');
            string RandomCode = "";
            int temp = -1;
            Random rand = new Random();
            for (int i = 0; i < CodeCount; i++)
            {
                if (temp != -1)
                {
                    rand = new Random(temp * i * ((int)DateTime.Now.Ticks));
                }
                int t = rand.Next(allCharArray.Length - 1);
                while (temp == t)
                {
                    t = rand.Next(allCharArray.Length - 1);
                }
                temp = t;
                RandomCode += allCharArray[t];
            }

            return RandomCode;
        }

        /// 获取小写的MD5签名结果
        /// </summary>
        /// <param name="encypStr">需要签名的串</param>
        /// <param name="charset">编码</param>
        /// <returns>返回小写的MD5签名结果</returns>
        public string GetMD5(string encypStr, string charset)
        {
            string retStr;
            MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();       //创建md5对象
            byte[] inputBye;
            byte[] outputBye;                                                   //使用GB2312编码方式把字符串转化为字节数组．
            try
            {
                inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr);
            }
            catch (Exception ex)
            {
                inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
                Console.WriteLine(ex);
            }
            outputBye = m5.ComputeHash(inputBye);
            retStr = System.BitConverter.ToString(outputBye);
            retStr = retStr.Replace("-", "").ToLower();
            return retStr;
        }

        /// <summary>
        /// 哈希256算法
        /// </summary>
        /// <param name="secret"></param>
        /// <param name="signKey"></param>
        /// <returns></returns>
        public string HmacSHA256(string secret, string signKey)
        {
            string result = string.Empty;
            using (HMACSHA256 hMACSHA = new HMACSHA256(Encoding.UTF8.GetBytes(signKey)))
            {
                byte[] inArray = hMACSHA.ComputeHash(Encoding.UTF8.GetBytes(secret));
                result = Convert.ToBase64String(inArray);
            }

            return result;
        }

        const string AES_IV = "LQHExIvX2021ZJSL";//16位    
        /// <summary>  
        /// AES加密算法  
        /// </summary>  
        /// <param name="input">明文字符串</param>  
        /// <param name="key">密钥（32位）</param>  
        /// <returns>字符串</returns>  
        public string CommonAESEncrypt(string input)
        {
            try
            {
                string key = "Zarathustra2021L";
                byte[] keyBytes = Encoding.UTF8.GetBytes(key.Substring(0, 16));
                using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
                {
                    aesAlg.Key = keyBytes;
                    aesAlg.IV = Encoding.UTF8.GetBytes(AES_IV.Substring(0, 16));

                    ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
                    using (MemoryStream msEncrypt = new MemoryStream())
                    {
                        using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                        {
                            using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                            {
                                swEncrypt.Write(input);
                            }
                            byte[] bytes = msEncrypt.ToArray();
                            return ByteArrayToHexString(bytes);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ArgumentException("加密失败");
            }

        }
        // <summary>  
        /// AES解密  
        /// </summary>  
        /// <param name="input">密文字节数组</param>  
        /// <param name="key">密钥（32位）</param>  
        /// <returns>返回解密后的字符串</returns>  
        public string CommonAESDecrypt(string input)
        {
            try
            {
                string key = "Zarathustra2021L";
                byte[] inputBytes = HexStringToByteArray(input);
                byte[] keyBytes = Encoding.UTF8.GetBytes(key.Substring(0, 16));
                using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
                {
                    aesAlg.Key = keyBytes;
                    aesAlg.IV = Encoding.UTF8.GetBytes(AES_IV.Substring(0, 16));

                    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
                    using (MemoryStream msEncrypt = new MemoryStream(inputBytes))
                    {
                        using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Read))
                        {
                            using (StreamReader srEncrypt = new StreamReader(csEncrypt))
                            {
                                return srEncrypt.ReadToEnd();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ArgumentException("解密失败");
            }

        }

        /// <summary>
        /// 将一个byte数组转换成一个格式化的16进制字符串
        /// </summary>
        /// <param name="data">byte数组</param>
        /// <returns>格式化的16进制字符串</returns>
        public string ByteArrayToHexString(byte[] data)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (byte b in data)
            {
                //16进制数字
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0'));
                //16进制数字之间以空格隔开
                //sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
            }
            return sb.ToString().ToUpper();
        }
        /// <summary>
        /// 将指定的16进制字符串转换为byte数组
        /// </summary>
        /// <param name="s">16进制字符串(如：“7F 2C 4A”或“7F2C4A”都可以)</param>
        /// <returns>16进制字符串对应的byte数组</returns>
        public byte[] HexStringToByteArray(string s)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            return buffer;
        }

    }
}
